package jude.java.money.article;

import java.io.File;

public class ManagerArticles {
	private static final int MAX = 10000;
	
	private String action;
	private File targetFolder;
	private File backupFolder;
	
	private int files;
	private int folders;
	private int left;
	
	public ManagerArticles(String action, File f) {
		this.action = action;
		this.targetFolder = new File(f.getAbsoluteFile() + File.separator + "articles");
		this.backupFolder = new File(f.getAbsoluteFile() + File.separator + "articles-backup");
	}

	public static void main(String[] args) {
		String path = ".";
		String action = "auto";
		if (args != null) {
			if (args.length > 0 && new File(args[0]).exists())
				path = args[0];
			if (args.length > 1)
				action = args[1];
		}
		File f = new File(path);
		new ManagerArticles(action, f).execute();
	}
	
	private void execute() {
		execute(this.action, this.targetFolder);
	}
	private void execute(String action, File f) {
		if (f == null || !f.exists())
			return;
		if ("clean".equals(action)) {
			System.out.println("cleaning: " + normalize(f.getAbsolutePath()));
			files = folders = left = 0;
			deletePublishedArticles(f);
			deleteEmptyFolders(f, true);
			System.out.println();
			System.out.println("删除已发布总数: " + files);
			System.out.println("删除空目录总数: " + folders);
			System.out.println("当前可用文章数: " + left);
			System.out.println();
			return;
		}
		int[] counts = new int[4];
		stat(f, counts);
		int backups = stat(backupFolder);
		if ("auto".equals(action)) {
			boolean changed = false;
			if (counts[1] > 0) {
				if (counts[0] - counts[1] + backups >= MAX) {
					execute("clean", f);
					changed = true;
				}
			}
			if (counts[0] - counts[1] > MAX * 2 && counts[0] - counts[1] - MAX > 0) {
				move(targetFolder, backupFolder, counts[0] - counts[1] - MAX);
				System.out.println("move to backup articles: " + (counts[0] - counts[1] - MAX));
				deleteEmptyFolders(targetFolder, false);
				changed = true;
			}
			if (backups > 0 && counts[0] - counts[1] < MAX && MAX - counts[0] - counts[1] > 0) {
				move(backupFolder, targetFolder, MAX - counts[0] - counts[1]);
				System.out.println("move from backup articles: " + (MAX - counts[0] - counts[1]));
				deleteEmptyFolders(backupFolder, false);
				changed = true;
			}
			if (!changed) {
				if (counts[0] > MAX * 3) {
					execute("clean", f);
				} else {
					System.out.println("do nothing");
				}
			}
			System.out.println();
			execute("stat", targetFolder);
		} else {//if ("stat".equals(action)) 
			System.out.println("当前文章数: " + counts[0]);
			System.out.println("已发布文章: " + counts[1]);
			System.out.println("未发布文章: " + (counts[0] - counts[1]));
			System.out.println("包含目录数: " + counts[2]);
			System.out.println("备份文章数: " + (backups > MAX ? (MAX + "+") : backups));
			System.out.println();
		}
	}
	
	private int move(File src, File dest, int count) {
		if (!src.isDirectory())// || !dest.isDirectory()
			return count;
		File[] children = src.listFiles();
		for (int i = 0; i < children.length; i++) {
			File f = children[i];
			String name = f.getName();
			if (f.isFile()) {
				moveFile(src, dest, name);
				count --;
				if (count <= 0)
					break;
			} else if (f.isDirectory()) {
				File dest2 = new File(dest.getPath() + File.separator + name);
				count = move(f, dest2, count);
				if (count <= 0)
					break;
			}
		}
		return count;
	}
	
	private void moveFile(File src, File dest, String name) {
		if (!dest.exists())
			dest.mkdirs();
		src = new File(src.getPath() + File.separator + name);
		dest = new File(dest.getPath() + File.separator + name);
		if (!src.renameTo(dest)) {
			System.out.println(".");
		}
	}
	
	private void deletePublishedArticles(File f) {
		if (f.isFile()) {
			if (f.getName().toLowerCase().endsWith(".published")) {
				f.delete();
				files ++;
				if (files % 200 == 0)
					System.out.println("delete published files: " + files);
			} else {
				left ++;
			}
			return;
		} else if (f.isDirectory()) {
			File[] children = f.listFiles();
			for (int i = 0; i < children.length; i++) {
				deletePublishedArticles(children[i]);
			}
		}
	}
	
	private boolean deleteEmptyFolders(File f, boolean stat) {
		if (!f.isDirectory())
			return false;
		File[] children = f.listFiles();
		boolean r = true;
		for (int i = 0; i < children.length; i++) {
			if (!children[i].isDirectory())
				return false;
			if (deleteEmptyFolders(children[i], stat)) {
				children[i].delete();
				if (stat) {
					folders ++;
					if (folders % 100 == 0)
							System.out.println("delete empty folders: " + folders);
				}
			} else {
				r = false;
			}
		}
		return r;
	}
	
	/**
	 * @param counts 1: files, 2: published, 3, folders, 4, empty folders
	 * */
	private boolean stat(File f, int[] counts) {
		if (f.isFile()) {
			counts[0] ++;
			if (f.getName().toLowerCase().endsWith(".published"))
				counts[1] ++;
			return false;
		} else if (f.isDirectory()) {
			counts[2] ++;
			File[] children = f.listFiles();
			boolean empty = true;
			for (int i = 0; i < children.length; i++) {
				empty = stat(children[i], counts) && empty;
			}
			if (empty)
				counts[3] ++;
			return empty;
		}
		return false;
	}
	
	private int stat(File f) {
		if (f.isFile()) {
			return 1;
		} else if (f.isDirectory()) {
			File[] children = f.listFiles();
			int n = 0;
			for (int i = 0; i < children.length; i++) {
				n += stat(children[i]);
				if (n > MAX)
					break;
			}
			return n;
		}
		return 0;
	}
	
	private String normalize(String path) {
		path = path.replace('\\', '/');
		path = path.replaceAll("/\\./", "/");
		path = path.replaceAll("/{2,}", "/");
		return path;
	}
}
